package oaep;
//package be.android.ocb.smartcard;
//
//import javacard.framework.APDU;
//import javacard.framework.Applet;
//import javacard.framework.ISO7816;
//import javacard.framework.ISOException;
//import javacard.framework.Util;
//import javacard.security.CryptoException;
//import javacard.security.HMACKey;
//import javacard.security.KeyBuilder;
//import javacard.security.KeyPair;
//import javacard.security.MessageDigest;
//import javacard.security.RandomData;
//import javacard.security.Signature;
//import javacardx.crypto.Cipher;
//import javacardx.framework.util.ArrayLogic;
//
//public class CopyOfAesOcb extends Applet{
//
//	private final static byte DERIVE_KEY = (byte)0x20; 
//	private final static byte GET_KEY = (byte)0x21; 
//
//	private final static byte ENCRYPT = (byte)0x60;
//	private final static byte DECRYPT = (byte)0x61;
//
//	short counter = 0x30;
//
//	public static void install(byte[] aArray, short	sOffset, byte bLength){
//		new CopyOfAesOcb(aArray, sOffset, bLength);
//	}
//
//	private CopyOfAesOcb(byte[] aArray, short sOffset, byte bLength){
//		register(aArray, (short) (sOffset + 1),	aArray[sOffset]);
//	}
//	//implementation for select() and deselect()
//	//from MultiSelectable interface
//	public boolean select(boolean appInstAlreadyActive){
//		return true;
//	}
//	public void deselect(boolean appInstStillActive){
//		return;
//	}
//
//	public void process(APDU apdu) throws ISOException {
//		if (selectingApplet())
//			return;
//		byte[] buffer = apdu.getBuffer();
//		if ( ((byte)(buffer[ISO7816.OFFSET_CLA] & (byte)0xFC)) != (byte)0x90 )	{
//			ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
//		}
//		switch (buffer[ISO7816.OFFSET_INS]) {
//		case (byte) 0x10:
//			buffer[0] = (byte) 'H';
//		buffer[1] = (byte) 'e';
//		buffer[2] = (byte) 'l';
//		buffer[3] = (byte) 'l';
//		buffer[4] = (byte) 'o';
//		buffer[5] = (byte) ',';
//		buffer[6] = (byte) ' ';
//		buffer[7] = (byte) 'S';
//		buffer[8] = (byte) 'm';
//		buffer[9] = (byte) 'a';
//		buffer[10] = (byte) 'r';
//		buffer[11] = (byte) 't';
//		buffer[12] = (byte) 'c';
//		buffer[13] = (byte) 'a';
//		buffer[14] = (byte) 'r';
//		buffer[15] = (byte) 'd';
//		buffer[16] = (byte) ':';
//		buffer[17] = (byte) ' ';
//		// increase counter by one and return counter value
//		buffer[18] = (byte) (counter++ % 10 + 0x30);
//		apdu.setOutgoingAndSend((short) 0, (short) 19);
//		break;
//		case DERIVE_KEY:
//			deriveKey(apdu);
//			break;
//		case GET_KEY:
//			//getKey(apdu);
//			break;
//		case ENCRYPT:
//			//encrypt(apdu);
//			break;
//		case DECRYPT:
//			//decrypt(apdu);
//			break;
//		default:
//			ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
//		}
//	}
//
//
//
//
//
//	private void deriveKey(APDU apdu) {
//		byte[] outbuffer;
//		short outLength;
//		try{
//			byte[] apduBuffer = apdu.getBuffer();
//			short dataLen = apdu.setIncomingAndReceive();
//			outbuffer = generatePBEKey(apduBuffer);
//			outLength = (short) outbuffer.length;
//		}catch(CryptoException e){
//			if (e.getReason() == CryptoException.NO_SUCH_ALGORITHM){
//				outbuffer = new byte[]{(byte)'N' ,(byte)'o' ,(byte)' ' ,(byte)'A' ,(byte)'l' ,(byte)'g' ,(byte)'o' ,(byte)'r', (byte)'i' } ;
//				outLength = (short)outbuffer.length;
//			}
//			outbuffer = new byte[]{(byte)'N' ,(byte)'o' ,(byte)' ' ,(byte)'S' ,(byte)'e' ,(byte)'c' ,(byte)'r' ,(byte)'e', (byte)'t' } ;
//			outLength = (short)outbuffer.length;
//		}		
//		apdu.setOutgoing();
//		apdu.setOutgoingLength(outLength);
//		apdu.sendBytesLong(outbuffer, (short) 0, outLength);
//
//	}
////
////	private void getKey(APDU apdu) {
////		// TODO Auto-generated method stub
////
////	}
////
////	private void encrypt(APDU apdu) {
////		// TODO Auto-generated method stub
////
////	}
////
////	private void decrypt(APDU apdu) {
////		// TODO Auto-generated method stub
////
////	}
////	/*int BLOCK_BITS  = 128;
////	int  PRE_COMP_BLOCKS = 32;
////	int BLOCK_SIZE  = (BLOCK_BITS >>> 3);
////	int TAG_LENGTH = BLOCK_SIZE;
////	/*private class L{
////		private byte[]  Lblock      = new byte[16];
////		public byte[] getLblock() {
////			return Lblock;
////		}
////	}
////
////	L[]  Lprecomp = new L[PRE_COMP_BLOCKS];*/
////
////	//protected byte[][]  L       = new byte[PRE_COMP_BLOCKS][BLOCK_SIZE]; // Precomputed L(i) values.
////	/*protected byte[]    L_inv   = new byte[BLOCK_SIZE]; // Precomputed L/x value
////	protected byte[]    tmp     = new byte[BLOCK_SIZE];
////	protected byte[]    offset  = new byte[BLOCK_SIZE]; // Offset (Z[i]) for current block
////	protected byte[]    chksum  = new byte[TAG_LENGTH]; // Checksum for computing tag
////
////
////	/*public static byte[] calculateRFC2104HMAC(byte[] data, byte[] key) {
////		byte[] result;
////		short blockSize = 64; //SHA-1 64 bytes blocksize
////		MessageDigest sha_1 = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
////		byte[] key2 = new byte[sha_1.getLength()];
////		if(key.length>blockSize){			
////			short key2Length = sha_1.doFinal(key, (short)0, (short)key.length, key2, (short) 0);
////		}
////		if(key.length<blockSize){
////			Util.arrayCopy(key, (short)0, key2, (short)0, (short)key.length);
////			Util.arrayFillNonAtomic(key2, (short)key.length, (short)(blockSize - key.length), (byte)0);
////		}
////
////
////
////}*/
//
//	HMACKey hmacK;
//
//
//	private byte[] generatePBEKey(byte[] password) {
//		byte salt[] = new byte[16];
//		//SecureRandom saltGen = SecureRandom.getInstance("SHA1PRNG");
//		RandomData saltGen = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
//		//saltGen.nextBytes(salt);
//		saltGen.generateData(salt, (short)0, (short)salt.length);
//
//		//DropboxUtil.uploadFile(salt, Constants.SALT_FILE);
//		//Log.e(TAG, "salt "+ salt);
//		//http://stackoverflow.com/questions/992019/java-256-bit-aes-password-based-encryption
//		/**
//		 *  Derive the key, given password and salt. 
//		 */
//		//SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
//		//HMACKey key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64, true);
//		//key.setKey(arg0, arg1, arg2)
//		hmacK = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64, true);
//		hmacK.setKey(password, (short)0, (short) password.length);
//		byte[] derivedKey = pbkdf2(salt);//,655536,128);
//		return salt;//derivedKey;
//		//KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
//		//SecretKey tmp = factory.generateSecret(spec);
//		//Log.e(TAG,tmp.getEncoded().length + " "+ new String(tmp.getEncoded()));
//		//SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
//		//Log.e(TAG,secret.getEncoded().length + " "+ new String(secret.getEncoded()));
//		//return secret.getEncoded();
//	}
//
//
//	/**
//	 * Core Password Based Key Derivation Function 2.
//	 * 
//	 * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2</a>
//	 * @param prf
//	 *            Pseudo Random Function (i.e. HmacSHA1)
//	 * @param S
//	 *            Salt as array of bytes. <code>null</code> means no salt.
//	 * @param c
//	 *            Iteration count (see RFC 2898 4.2)
//	 * @param dkLen
//	 *            desired length of derived key.
//	 * @return internal byte array
//	 */
//	private byte[] pbkdf2(byte[] S/*, int c, int dkLen*/)
//	{
//		short c = 32000;//65536;
//		short dkLen = 128;
//		if (S == null)
//		{
//			S = new byte[0];
//		}
//		int hLen = KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64;
//		//int l = ceil(dkLen, hLen);
//		int m = 0;
//		if (dkLen % hLen > 0)
//		{
//			m = 1;
//		}
//		int l =  dkLen / hLen + m;
//		//ciel
//		int r = dkLen - (l - 1) * hLen;
//		byte T[] = new byte[l * hLen];
//		int ti_offset = 0;
//		for (int i = 1; i <= l; i++)
//		{
//			//fFunction(T, ti_offset, S, c, i);
//			//fFunction(byte[] dest, int offset, byte[] S, int c,int blockIndex)
//			byte U_r[] = new byte[hLen];
//
//			// U0 = S || INT (i);
//			byte U_i[] = new byte[S.length + 4];
//			Util.arrayCopy(S, (short)0, U_i, (short)0, (short)S.length);
//			//INT(U_i, S.length, i);
//			//protected void INT(byte[] dest, int offset, int i)
//
//			U_i[S.length + 0] = (byte) (i / (256 * 256 * 256));
//			U_i[S.length + 1] = (byte) (i / (256 * 256));
//			U_i[S.length + 2] = (byte) (i / (256));
//			U_i[S.length + 3] = (byte) (i);
//
//			for (int j = 0; j < c; j++){
//
//				//U_i = prf.doFinal(U_i);
//				/*HMACKey hmacK = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64, true);
//	        	hmacK.setKey(U_i, (short)0, (short) U_i.length);
//	        	hmacK.getKey(U_i, (short)0);*/
//				Signature sig = Signature.getInstance(Signature.ALG_HMAC_SHA1, false);
//				sig.init(hmacK, Signature.MODE_SIGN);
//				sig.sign(U_i, (short)0, (short)U_i.length, U_i, (short)0);
//
//				xor(U_r, U_i);
//			}
//			Util.arrayCopy(U_r, (short)0, T, (short)ti_offset, (short)hLen);				
//			ti_offset += hLen;
//		}
//		if (r < hLen)
//		{
//			// Incomplete last block
//			byte DK[] = new byte[dkLen];
//			Util.arrayCopy(T, (short)0, DK, (short)0, (short)dkLen);
//			return DK;
//		}
//		return T;
//	}
////
////
////
////	/**
////	 * Integer division with ceiling function.
////	 * 
////	 * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 2.</a>
////	 * @param a
////	 * @param b
////	 * @return ceil(a/b)
////	 */
////	/*private int ceil(int a, int b)
////	{
////		int m = 0;
////		if (a % b > 0)
////		{
////			m = 1;
////		}
////		return a / b + m;
////	}*/
////
////	/**
////	 * Function F.
////	 * 
////	 * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
////	 * @param dest
////	 *            Destination byte buffer
////	 * @param offset
////	 *            Offset into destination byte buffer
////	 * @param prf
////	 *            Pseudo Random Function
////	 * @param S
////	 *            Salt as array of bytes
////	 * @param c
////	 *            Iteration count
////	 * @param blockIndex
////	 */
////	/*protected void fFunction(byte[] dest, int offset, byte[] S, int c,
////			int blockIndex)
////	{
////		int hLen = KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64;
////		byte U_r[] = new byte[hLen];
////
////		// U0 = S || INT (i);
////		byte U_i[] = new byte[S.length + 4];
////		Util.arrayCopy(S, (short)0, U_i, (short)0, (short)S.length);
////		INT(U_i, S.length, blockIndex);
////
////		for (int i = 0; i < c; i++){
////
////			//U_i = prf.doFinal(U_i);
////			//HMACKey hmacK = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64, true);
////        	//hmacK.setKey(U_i, (short)0, (short) U_i.length);
////        	//hmacK.getKey(U_i, (short)0);
////			Signature sig = Signature.getInstance(Signature.ALG_HMAC_SHA1, false);
////			sig.init(hmacK, Signature.MODE_SIGN);
////			sig.sign(U_i, (short)0, (short)U_i.length, U_i, (short)0);
////
////			xor(U_r, U_i);
////		}
////		Util.arrayCopy(U_r, (short)0, dest, (short)offset, (short)hLen);
////	}*/
//
//	/**
//	 * Block-Xor. Xor source bytes into destination byte buffer. Destination
//	 * buffer must be same length or less than source buffer.
//	 * 
//	 * @param dest
//	 * @param src
//	 */
//	protected void xor(byte[] dest, byte[] src)
//	{
//		for (int i = 0; i < dest.length; i++)
//		{
//			dest[i] ^= src[i];
//		}
//	}
////
////	/**
////	 * Four-octet encoding of the integer i, most significant octet first.
////	 * 
////	 * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
////	 * @param dest
////	 * @param offset
////	 * @param i
////	 */
////	/*protected void INT(byte[] dest, int offset, int i)
////	{
////		dest[offset + 0] = (byte) (i / (256 * 256 * 256));
////		dest[offset + 1] = (byte) (i / (256 * 256));
////		dest[offset + 2] = (byte) (i / (256));
////		dest[offset + 3] = (byte) (i);
////	}*/
////
////	/***
////	 *  function ocb-aes-encrypt(K, M, Nonce)
////    begin
////        Offset = AES(K, Nonce xor L) 
////        Checksum = 0
////        for i = 1 to m-1 do begin
////            Offset = Offset xor L(ntz(i))
////            Checksum = Checksum xor M[i]
////            C[i] = Offset xor AES(K, M[i] xor Offset) 
////        end
////        Offset = Offset xor L(ntz(m))
////        Pad = AES (K, len(M[m]) xor L(-1) xor Offset)
////        C[m] = M[m] xor (the first |M[m]| bits of Pad)
////        Checksum = Checksum xor Pad xor C[m]0*
////        FullTag = AES(K, Checksum xor Offset) 
////        Tag = a prefix of FullTag (of the desired length)
////        return C[1]... C[m-1] C[m] Tag 
////    end
////	 */
////
////	/*public byte[] encrypt(byte[] pt, int ptLen, byte[] nonce, byte[] tag){
////
////		int ptPos = 0;
////
////		// Create ciphertext
////		byte[] ct = new byte[ptLen];
////		int ctPos = 0;
////
////		//Arrays.fill(chksum, (byte)0);                       // Zero the checksum
////		chksum[0] = (byte)0;
////		ArrayLogic.arrayFillGenericNonAtomic(chksum, (short)0, (short)chksum.length, chksum, (short)0);
////
////		//xorBlock(offset, L[0], nonce);          			// Calculate R, aka Z[0]
////		//xorBlock(offset, Lprecomp[0].getLblock(), nonce);
////		offset = encryptAes(offset);
////
////
////		// Process blocks 1 .. m-1
////		int i;
////		for (i = 1; ptLen > BLOCK_SIZE; i++) {
////			//xorBlock(offset, offset, L[ntz(i)]);			// Update the offset (Z[i] from Z[i-1])
////			//xorBlock(offset, offset, Lprecomp[ntz(i)].getLblock());
////			xorBlock(chksum, chksum, pt, ptPos);			// Update the checksum
////			xorBlock(tmp, offset, pt, ptPos);				// xor the plaintext block with Z[i]
////			tmp = encryptAes(tmp);							// Encipher the block
////			xorBlock(ct, ctPos, offset, tmp);				// xor Z[i] again, writing result to ciphertext pointer
////			ptLen -= BLOCK_SIZE;
////			ptPos += BLOCK_SIZE;
////			ctPos += BLOCK_SIZE;
////		}
////
////		// Process block m
////		//xorBlock(offset, offset, L[ntz(i)]);                // Update the offset (Z[m] from Z[m-1])
////		//xorBlock(offset, offset, Lprecomp[ntz(i)].getLblock()); 
////		xorBlock(tmp, offset, L_inv);                       // xor L . x^{-1} and Z[m]
////		tmp[BLOCK_SIZE - 1] ^= (byte)(ptLen << 3);          // Add in final block bit-length
////		tmp = encryptAes(tmp);
////
////		for (int t = 0; t < ptLen; t++) {
////			ct[ctPos + t] = (byte)(pt[ptPos + t] ^ tmp[t]); // xor pt with block-cipher output to get ct
////			tmp[t] = pt[ptPos + t];                         // Add to checksum the ptLen bytes of plaintext...
////		}
////		xorBlock(chksum, chksum, tmp);                      // ... followed by the last (16 - ptLen) bytes of block-cipher output
////
////		// Calculate tag
////		xorBlock(chksum, chksum, offset);
////		tmp = encryptAes(chksum);
////		Util.arrayCopy(tmp, (short)0, tag, (short)0, (short)TAG_LENGTH);
////
////		return ct;
////	}
////
////	/**
////	 * Given a nonce starting at offset noncePos of the nonce byte array,
////	 * decrypt ctLen elements of byte array ct starting at offset ctPos, and
////	 * verifying a tag starting at offset tagPos of the tag byte array.
////	 *
////	 * @param       ct          ciphertext buffer.
////	 * @param       ctPos       start index of ciphertext on ct.
////	 * @param       ctLen       byte length of ciphertext.
////	 * @param       nonce       nonce array (BLOCK_SIZE bytes).
////	 * @param       noncePos    start index of nonce.
////	 * @param       tag         input tag buffer.
////	 * @param       tagPos      start index of tag.
////	 *
////	 * @return      the resulting plaintext, a byte array of same length as ct
////	 *              if decryption is successfull, or else null if the tag does
////	 *              not correctly verify.
////	 * 
////	 * @warning     ct, nonce, and tag must not overlap.
////	 */
////	//public final byte[] decrypt(byte[] ct, int ctLen, byte[] nonce,  byte[] tag)
////	/*throws IllegalArgumentException*/ {
////
////		/*int ctPos = 0;
////		// Create plaintext
////		byte[] pt = new byte[ctLen];
////		int ptPos = 0;
////
////		//Arrays.fill(chksum, (byte)0);               // Zero checksum
////		chksum[0] = (byte)0;
////		ArrayLogic.arrayFillGenericNonAtomic(chksum, (short)0, (short)chksum.length, chksum, (short)0);
////
////		xorBlock(offset, L[0], nonce);    			// Calculate R, aka Z[0]
////		offset = encryptAes(offset);
////
////		// Process blocks 1 .. m-1
////		int i;
////		for (i = 1; ctLen > BLOCK_SIZE; i++) {
////			xorBlock(offset, offset, L[ntz(i)]);            // Update the offset (Z[i] from Z[i-1])
////			xorBlock(tmp, offset, ct, ctPos);               // xor ciphertext block with Z[i]
////			tmp = decryptAes(tmp);                          // Decipher the next block-cipher block
////
////			xorBlock(pt, ptPos, offset, tmp);               // xor Z[i] again, writing result to plaintext pointer
////			xorBlock(chksum, chksum, pt, ptPos);            // Update the checksum
////			ctLen -= BLOCK_SIZE;
////			ctPos += BLOCK_SIZE;
////			ptPos += BLOCK_SIZE;
////		}
////
////		// Process block m
////		xorBlock(offset, offset, L[ntz(i)]);                // Update the offset (Z[m] from Z[m-1])
////		xorBlock(tmp, offset, L_inv);                       // xor L . x^{-1} and Z[m]
////		tmp[BLOCK_SIZE - 1] ^= (byte)(ctLen << 3);          // Add in final block bit-length
////		tmp = encryptAes(tmp);
////
////		for (int t = 0; t < ctLen; t++) {
////			pt[ptPos + t] = (byte)(ct[ctPos + t] ^ tmp[t]); // xor ct with block-cipher output to get pt
////			tmp[t] = pt[ptPos + t];                         // Add to checksum the ctLen bytes of plaintext...
////		}
////		xorBlock(chksum, chksum, tmp);                      // ... followed by the last (16 - ptLen) bytes of block-cipher output
////
////		// Calculate and verify tag
////		xorBlock(chksum, chksum, offset);
////		tmp = encryptAes(chksum);
////		for (int t = 0; t < TAG_LENGTH; t++) {
////			if (tmp[t] != tag[0 + t]) {
////				//Arrays.fill(pt, (byte)0);
////				pt[0] = (byte)0;
////				ArrayLogic.arrayFillGenericNonAtomic(pt, (short)0, (short)pt.length, pt, (short)0);
////
////				pt = null;
////				break;
////			}
////		}*/
////
////	//	return null;//pt;
////	//}
////
////	//SecretKey skey;
////	//SecretKeySpec skeySpec;
////	byte[] aesOcbKey = new byte[16];
////
////	/**
////	 * Initialise the underlying AES cipher with a symmetric key.
////	 *
////	 * @param   cipherKey   the symmetric AES key.
////	 * @param   keyBits     the key size in bits (128, 192, or 256).
////	 *
////	 * @throws  IllegalArgumentException    if the key is null or
////	 *                      its length is not 128, 192, or 256.
////	 * @throws NoSuchAlgorithmException 
////	 * @throws InvalidKeySpecException 
////	 */
////	public final void init(byte[] k, int keyBits)
////	/*throws IllegalArgumentException, NoSuchAlgorithmException, InvalidKeySpecException*/{
////		if (k == null) {
////			//TODO
////			//throw new IllegalArgumentException("Null key");
////		}
////		//if (keyBits != 128 && keyBits != 192 && keyBits != 256) {
////		//throw new IllegalArgumentException("Invalid AES key size: " + keyBits + " bits.");
////		//}
////		// Initialize AES keys
////		aesOcbKey = k;
////
////		// Precompute L[i]-values (L[0] is synonym of L)
////		//byte[] L0 = L[0];
////		/*byte[] L0 = Lprecomp[0].Lblock;
////		//Arrays.fill(L0, (byte)0);
////		L0[0] = (byte)0;
////		ArrayLogic.arrayFillGenericNonAtomic(L0, (short)0, (short)L0.length, L0, (short)0);
////
////
////		//aes.encrypt(L0, L0);
////		L0 = encryptAes(L0);
////
////		for (int i = 1; i < PRE_COMP_BLOCKS; i++) {
////			// L[i] = L[i - 1] * x
////			//byte[] L_cur = L[i], L_pre = L[i - 1];
////			//byte[] L_cur = Lprecomp[i].Lblock, L_pre = Lprecomp[i - 1].getLblock();
////			for (int t = 0; t < BLOCK_SIZE - 1; t++) {
////				L_cur[t] = (byte)((L_pre[t] << 1) | ((L_pre[t + 1] >>> 7) & 1));
////			}
////			L_cur[BLOCK_SIZE - 1] = (byte)((L_pre[BLOCK_SIZE - 1] << 1) ^ ((L_pre[0] & 0x80) != 0 ? 0x87 : 0));
////		}
////
////		// Precompute L_inv = L / x = L * x^{-1}
////		for (int i = BLOCK_SIZE - 1; i > 0; i--) {
////			L_inv[i] = (byte)(((L0[i] & 0xff) >>> 1) | ((L0[i - 1] & 1) << 7));
////		}
////		L_inv[0] = (byte)((L0[0] & 0xff) >>> 1);
////		if ((L0[BLOCK_SIZE - 1] & 1) != 0) {
////			L_inv[0] ^= 0x80;
////			L_inv[BLOCK_SIZE - 1] ^= 0x43;
////		}*/
////	}
////
////	/*protected final void xorBlock(byte[] dst, int pos,
////			byte[] src1, byte[] src2) {
////		for (int i = 0; i < BLOCK_SIZE; i++) {
////			dst[pos + i] = (byte)(src1[i] ^ src2[i]);
////		}
////	}
////
////	protected final void xorBlock(byte[] dst, byte[] src1,
////			byte[] src2, int pos) {
////		for (int i = 0; i < BLOCK_SIZE; i++) {
////			dst[i] = (byte)(src1[i] ^ src2[pos + i]);
////		}
////	}
////
////	protected final void xorBlock(byte[] dst, byte[] src1, byte[] src2) {
////		for (int i = 0; i < BLOCK_SIZE; i++) {
////			dst[i] = (byte)(src1[i] ^ src2[i]);
////		}
////	}
////
////	/**
////	 * Count the number of trailing zeroes in integer i.
////	 *
////	 * @return  0 <= ntz <= 32.
////	 */
////	protected static final int ntz(int i) {
////		/*
////		 * N.B. this function is not as bad as it might seem:
////		 * assuming the argument i is uniformly distributed,
////		 * the probability that ntz(i) = k is 2^(-k-1),
////		 * therefore the expected value of ntz(i) is < 1.
////		 */
////		int result = 0;
////		while ((i & 1) == 0) {
////			i >>>= 1;
////		result++;
////		}
////		return result;
////	}
////
////	private final byte AESOCB_ALG = Cipher.ALG_AES_BLOCK_128_ECB_NOPAD;
////
////	private byte[] encryptAes(byte[] src){
////		byte[] result = null;
////
////		Cipher encryptCipher = Cipher.getInstance(AESOCB_ALG, false);
////		//encryptCipher.init(aesOcbKey, Cipher.MODE_ENCRYPT);
////		encryptCipher.doFinal(src, (short) 0, (short) src.length, result, (short) 0);
////
////		/*try {
////			SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
////			Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
////			cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
////			result = cipher.doFinal(src);
////		} catch (IllegalBlockSizeException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (BadPaddingException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (InvalidKeyException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (NoSuchAlgorithmException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (NoSuchPaddingException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		}*/
////		return result;
////	}
////
////	private byte[] decryptAes(byte[] src){
////		byte[] result = null;
////		/*try {
////			//KeyGenerator kgen = KeyGenerator.getInstance("AES");
////			//kgen.init(128); // 192 and 256 bits may not be available
////			// Generate the secret key specs.
////			//skey = kgen.generateKey();
////			//byte[] raw = skey.getEncoded();
////			SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
////			Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
////			cipher.init(Cipher.DECRYPT_MODE, skeySpec);
////			result = cipher.doFinal(src);
////		} catch (IllegalBlockSizeException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (BadPaddingException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (InvalidKeyException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (NoSuchAlgorithmException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		} catch (NoSuchPaddingException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		}*/
////		return result;
////	}
//
//
//}
